import {
	IParam,
	deepCopy,
	srfFilePath2,
	ICtrlAbility,
	IEvent,
	IViewLogicInput,
	ICtrlStore,
	IFormStore,
	IFormAbility,
	IMDCtrlAbility,
	IMDCtrlStore,
	IExpCtrlModel,
	IExpCtrlStore,
	IExpCtrlAbility,
	IGridStore,
	IGridAbility,
	computedNavData,
	IPanelStore,
	IPanelAbility,
	IPortletStore,
	IPortletAbility,
	IDECtrlAbility,
	IViewAbility,
	createUUID,
	IContext,
	ILoadingHelper,
	IViewCtx,
} from '@/core';
import {
	ICtrlController,
	IExpCtrlController,
	IFormController,
	IGridController,
	IMDCtrlController,
	IPanelController,
	IPortletController,
} from '@/core/interface/widgets/controller';
import { CtrlActionType, ICtrlEvent } from '@/core/interface/widgets/event/i-ctrl-event';
import { ICtrlModel } from '@/core/interface/widgets/model/i-ctrl-model';
import { QXEvent } from 'qx-util';
import { PropType } from 'vue';

/**
 * 部件事件绑定
 *
 * @export
 * @template T
 * @template A
 * @param {Function} emit
 * @return {*}  QXEvent<ICtrlEvent<T, A>>
 */
export function useEventBind<T, A extends ICtrlAbility>(
	emit: Function
): QXEvent<ICtrlEvent<T, A>> {
	const evt = new QXEvent<ICtrlEvent<T, A>>();
	//  绑定事件回调
	evt.on('ctrlAction', (controlName: string, action: T, data: any) => {
		emit('ctrl-action', controlName, action, data);
	});
	evt.on('ctrlInit', (controlName: string, data: A) => {
		emit('ctrl-init', controlName, data);
	});
	evt.on('ctrlDestroy', (controlName: string, data: IParam) => {
		emit('ctrl-destroy', controlName, data);
	});
	return evt;
}

/**
 * 处理部件初始化
 *
 * @export
 * @template C
 * @param {C} controller 控制器
 * @param {string} name 部件名称
 * @param {ICtrlAbility} ability 部件能力
 */
export function handleCtrlInit<
	C extends ICtrlController<ICtrlStore, ICtrlAbility>
>(controller: C, name: string, ability: ICtrlAbility | IViewAbility) {
	controller.setSubAbility(name, ability);
}

/**
 * 处理子部件挂载
 *
 * @export
 * @template C
 * @param {C} controller
 * @param {string} name
 * @param {IParam} data
 */
export function handleCtrlMounted<
	C extends ICtrlController<ICtrlStore, ICtrlAbility>
>(controller: C, name: string, data: IParam) {
	controller.handleCtrlMounted(name, data);
}

/**
 * 处理部件行为
 *
 * @export
 * @template C
 * @template A
 * @param {C} controller 控制器
 * @param {string} name 部件名称
 * @param {A} action 行为标识
 * @param {IParam[]} data 数据
 */
export function handleCtrlAction<
	C extends ICtrlController<ICtrlStore, ICtrlAbility>,
	A extends string
>(controller: C, name: string, action: A, data: IParam[]) {
	controller.handleCtrlAction(name, action, data);
}

/**
 * 处理部件销毁
 *
 * @export
 * @template C
 * @param {C} controller 控制器
 * @param {string} name 部件名称
 * @param {IParam} data 数据
 */
export function handleCtrlDestroy<
	C extends ICtrlController<ICtrlStore, ICtrlAbility>
>(controller: C, name: string, data: IParam) {
	controller.handleCtrlDestroy(name, data);
}

/**
 * 处理部件子组件行为
 *
 * @export
 * @param {(IFormController | IPortletController)} controller
 * @param {IEvent<string>} actionParam
 */
export function handleComponentAction(
	controller:
		| IFormController<IFormStore, IFormAbility>
		| IPortletController<IPortletStore, IPortletAbility>
		| IGridController<IGridStore, IGridAbility>
		| IPanelController<IPanelStore, IPanelAbility>,
	actionParam: IEvent<string>,
	index?: number
) {
	if ((controller.getModel<ICtrlModel>().controlType == 'GRID')) {
		(
			controller as IGridController<IGridStore, IGridAbility>
		).handleComponentAction(actionParam, index as number);
	} else {
		(
			controller as
				| IFormController<IFormStore, IFormAbility>
				| IPortletController<IPortletStore, IPortletAbility>
				| IPanelController<IPanelStore, IPanelAbility>
		).handleComponentAction(actionParam);
	}
}

/**
 * 多数据部件页码变化
 *
 * @export
 * @param {IMDCtrlController} controller
 * @param {number} currentPage
 */
export function handlePageChange(
	controller: IMDCtrlController<IMDCtrlStore, IMDCtrlAbility>,
	currentPage: number
) {
	controller.handlePageChange(currentPage);
}

/**
 * 多数据部件分页大小变化
 *
 * @export
 * @param {IMDCtrlController} controller
 * @param {number} size
 */
export function handlePageSizeChange(
	controller: IMDCtrlController<IMDCtrlStore, IMDCtrlAbility>,
	size: number
) {
	controller.handlePageSizeChange(size);
}

/**
 * 多数据部件排序变化
 *
 * @export
 * @param {IMDCtrlController} controller
 * @param {string} sortField
 * @param {('asc' | 'desc' | '')} sortDir
 */
export function handleSortChange(
	controller: IMDCtrlController<IMDCtrlStore, IMDCtrlAbility>,
	sortField: string,
	sortDir: 'asc' | 'desc' | ''
) {
	controller.handleSortChange(sortField, sortDir);
}
/**
 * 多数据部件选中数据改变
 *
 * @export
 * @param {IMDCtrlController<IMDCtrlStore, IMDCtrlAbility>} controller
 * @param {IParam[]} selections
 */
export function handleSelectionChange(
	controller: IMDCtrlController<IMDCtrlStore, IMDCtrlAbility>,
	selections: IParam[]
) {
	controller.handleSelectionChange(selections);
}
/**
 * 多数据部件行为点击
 *
 * @export
 * @param {IMDCtrlController} controller
 * @param {IViewLogicInput} logic
 * @param {IParam} data
 * @param {MouseEvent} event
 */
export function handleActionClick(
	controller: IMDCtrlController<IMDCtrlStore, IMDCtrlAbility>,
	logic: IViewLogicInput,
	data: IParam,
	event: MouseEvent
) {
	const ability = controller.getAbility();
	const { context, viewParams } = controller.getStore();
	App.getViewLogicHelper().executeViewLogic(
		context,
		viewParams,
		[data],
		event,
		ability,
		logic
	);
}

/**
 * 计算部件上下文
 *
 * @export
 * @param {IParam} props
 * @return {*}
 */
export function useCtrlContext(props: IParam) {
	const { context: propContext } = props;
	const context = deepCopy(propContext);
	if (context.srfparentdename && context.srfparentkey) {
		Object.assign(context, {
			[context.srfparentdename.toLowerCase()]: context.srfparentkey,
		});
	}
	return context;
}

/**
 * 计算部件导航参数
 *
 * @export
 * @param {IParam} model
 * @param {IParam} props
 * @return {*}  {{ context: IParam; viewParams: IParam }}
 */
export function useCtrlParams(
	model: IParam,
	props: IParam
): { context: IParam; viewParams: IParam } {
	const {
		context: propContext,
		viewParams: propViewParams,
		localContext,
		localViewParams,
	} = props;
	const context = deepCopy(propContext);
	const viewParams = deepCopy(propViewParams);
	if (context.srfparentdename && context.srfparentkey) {
		Object.assign(context, {
			[context.srfparentdename.toLowerCase()]: context.srfparentkey,
		});
	}
	if (localContext && Object.keys(localContext).length > 0) {
		const _context = computedNavData({}, context, viewParams, localContext);
		Object.assign(context, _context);
	}
	if (localViewParams && Object.keys(localViewParams).length > 0) {
		const _viewParams = computedNavData(
			{},
			context,
			viewParams,
			localViewParams
		);
		Object.assign(viewParams, _viewParams);
	}
	return { context, viewParams };
}

/**
 * 设置导航参数
 *
 * @param {ICtrlController} controller
 * @param {IParam} props
 */
function computeNavParams(
	controller: ICtrlController<ICtrlStore, ICtrlAbility>,
	props: IParam
) {
	const model = controller.getModel<IParam>();
	const { context, viewParams } = useCtrlParams(model, props);
	controller.setNavParams(context, viewParams);
}

/**
 * 导航参数绑定
 *
 * @export
 * @param {ICtrlController} controller
 * @param {IParam} props
 */
export function useNavParamsBind(
	controller: ICtrlController<ICtrlStore, ICtrlAbility>,
	props: IParam
) {
	watch(
		() => props.context,
		() => {
			computeNavParams(controller, props);
		},
		{ immediate: true, deep: true }
	);
	watch(
		() => props.viewParams,
		() => {
			computeNavParams(controller, props);
		},
		{ immediate: true, deep: true }
	);
}

/**
 * 获取部件类名
 *
 * @export
 * @param {IParam} model
 * @param {IParam} [props={}]
 * @return {*}  {IParam}
 */
export function getCtrlClassNames(model: IParam, props: IParam = {}): IParam {
	const classNames: IParam = {
		'control-container': true,
	};
	if (model.controlType) {
		Object.assign(classNames, {
			[`app-control-${model.controlType.toLowerCase()}`]: true,
		});
	}
	if (model.codeName) {
		Object.assign(classNames, { [srfFilePath2(model.codeName)]: true });
	}
	if (model.cssName) {
		Object.assign(classNames, { [model.cssName]: true });
	}
	return classNames;
}

/**
 * 获取导航栏类名
 *
 * @export
 * @param {IExpCtrlModel} model
 * @param {IParam} props
 * @param {IParam} [customClassNames={}]
 * @return {*}
 */
export function getExpBarClassNames(
	model: IExpCtrlModel,
	props: IParam,
	customClassNames: IParam = {}
) {
	//  TODO 计算父视图时候有快速分组
	const classNames = getCtrlClassNames(model, props);
	Object.assign(classNames, {
		'app-control-expbar': true,
	});
	Object.assign(classNames, customClassNames);
	return classNames;
}

/**
 * 工具栏点击
 *
 * @export
 * @param {IViewController} controller
 * @param {string} name
 * @param {MouseEvent} event
 * @param {IParam} [logic]
 * @return {*}
 */
export function handleToolbarItemClick(
	controller: ICtrlController<ICtrlStore, ICtrlAbility>,
	name: string,
	event: MouseEvent,
	logic?: IViewLogicInput
) {
	if (!logic) {
		console.warn('无事件逻辑');
		return;
	}
	const model = controller.getModel<ICtrlModel>();
	if (!logic.xDataCtrlName) {
		console.warn('无数据目标部件');
	} else {
		// 触发源为数据部件或当前部件(适配导航工具栏)
		if (
			model?.xDataCtrlName?.toLowerCase() ===
				logic.xDataCtrlName.toLowerCase() ||
			model.name.toLowerCase() === logic.xDataCtrlName.toLowerCase()
		) {
			// 获取参数
			const { context, viewParams } = controller.getStore();
			const tempContext = deepCopy(context);
			const tempViewParams = deepCopy(viewParams);
			// 获取能力
			const ability = controller.getSubAbility<ICtrlAbility>(
				logic.xDataCtrlName.toLowerCase()
			) as IDECtrlAbility;
			// 获取数据
			let data: IParam[] = [];
			if (ability) {
				data = ability.getData();
			}
			// 执行视图逻辑
			App.getViewLogicHelper().executeViewLogic(
				tempContext,
				tempViewParams,
				data,
				event,
				ability,
				logic
			);
		}
	}
}

/**
 * 处理导航部件快速搜索
 *
 * @export
 * @param {IExpCtrlController<IExpCtrlStore, IExpCtrlAbility>} controller
 * @param {string} searchValue
 */
export function handleQuickSearch(
	controller: IExpCtrlController<IExpCtrlStore, IExpCtrlAbility>,
	searchValue: string
) {
	controller.search(searchValue);
}


/**
 * 部件输入参数
 *
 * @return {*}
 */
export function useCtrlProps() {
	return {
		name: String,
		context: Object as PropType<IContext>,
		viewParams: Object as PropType<IParam>,
		localContext: Object as PropType<IParam>,
		localViewParams: Object as PropType<IParam>,
		pLoadingHelper: Object as PropType<ILoadingHelper>,
		pViewCtx: Object as PropType<IViewCtx>,
		closeView: Function,
	};
}

/**
 * 部件基础参数
 *
 * @export
 * @param {ICtrlModel} model
 * @param {IParam} props
 */
export function useCtrlBasic(model: ICtrlModel, props: IParam) {
	return {
		controlID: createUUID(),
		model,
		useNavParamsBind,
		useEventBind,
		handleActionClick,
		handleComponentAction,
	};
}

/**
 * 部件行为
 *
 * @export
 */
export function useCtrlAction(controller: any) {
	return {};
}

/**
 * 部件控制器输入参数
 *
 * @param {*} props
 * @return {*}
 */
export function useCtrlControllerParams<S extends ICtrlStore, M extends ICtrlModel>(
	model: M,
	props: any,
	evt: QXEvent<ICtrlEvent<CtrlActionType, ICtrlAbility>>,
    otherParams: IParam = {},
) {
    const { controlID } = otherParams;
	return {
		name: props.name,
		model,
		evt,
		controlID: controlID,
		pLoadingHelper: props.pLoadingHelper,
		pViewCtx: props.pViewCtx,
		closeView: props.closeView,
		handler: (data: S) => {
			return reactive(data);
		},
		
	};
}